package org.e_gold.service.impl;

import java.util.HashMap;
import java.util.List;
import java.util.Map;

import org.apache.commons.collections.MapUtils;
import org.apache.commons.lang.StringUtils;
import org.apache.log4j.Logger;
import org.e_gold.dao.CookieDAO;
import org.e_gold.dto.Browser;
import org.e_gold.dto.Cookies;
import org.e_gold.model.Cookie;
import org.e_gold.service.CookieService;
import org.e_gold.util.BrowserTypeENUM;
import org.e_gold.util.Constant;
import org.jsoup.Connection;
import org.jsoup.Jsoup;
import org.jsoup.nodes.Document;
import org.springframework.beans.factory.InitializingBean;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.HttpStatus;
import org.springframework.stereotype.Component;

@Component
public abstract class _NavigatorAbstract implements Constant, InitializingBean {

    private static final Logger logger = Logger.getLogger(_NavigatorAbstract.class);

    @Autowired
    private CookieService cookieService;

    @Autowired
    protected CookieDAO cookieDAO;

    @Override
    public void afterPropertiesSet() throws Exception {

        // // init header + cookies
        // headers = prepareBasicHeaders();
        // if (cookieDAO.findAll() != null && cookieDAO.findAll().size() > 0) {
        // // re-store cookie for logined session or basic session for the first time
        // if (cookies == null) {
        // cookies = new Cookies();
        // }
        // if (cookies.getCookies() == null) {
        // cookies.setCookies(cookieDAO.findAll());
        // }
        // headers.put(COOKIE, cookies.getCookie());
        // } else {
        // try {
        // redirectNavigator(DEFAULT_URL);
        // } catch (Exception e) {
        // e.printStackTrace();
        // }
        // }
    }

    public Connection navigator(String url, Browser browser) {

        Connection connection = Jsoup.connect(url);
        Map<String, String> headers = browser.getHeaders();
        Cookies cookies = browser.getCookies();
        if (headers == null) {
            // prepare headers first time
            browser.setHeaders(prepareBasicHeaders(browser.getBrowserType()));
            headers = browser.getHeaders();
        }
        for (Map.Entry<String, String> entry : headers.entrySet()) {
            connection.header(entry.getKey(), entry.getValue());
        }
        if (cookies != null && cookies.getCookieMap() != null && cookies.getCookieMap().size() > 0) {
            connection.cookies(cookies.getCookieMap());
            connection.header(COOKIE, cookies.getCookie());
        }
        connection.followRedirects(false);
        return connection;
    }

    public Map<String, String> prepareBasicHeaders(String browserType) {

        Map<String, String> basicHeader = new HashMap<String, String>();
        basicHeader.put(ACCEPT, ACCEPT_DATA);
        basicHeader.put(ACCEPT_ENCODING, ACCEPT_ENCODING_DATA);
        basicHeader.put(ACCEPT_LANGUAGE, ACCEPT_LANGUAGE_DATA);
        basicHeader.put(CONNECTION, CONNECTION_DATA);
        basicHeader.put(HOST, HOST_DATA);
        basicHeader.put(CACHE_CONTROL, CACHE_CONTROL_DATA);
        basicHeader.put(PRAGMA, PRAGMA_DATA);

        if (browserType == null) {
            basicHeader.put(USER_AGENT, USER_AGENT_DATA_FIREFOX);
        } else {
            if (StringUtils.isNotEmpty(browserType)) {
                if (BrowserTypeENUM.IPAD_VERSION.toString().equalsIgnoreCase(browserType)) {
                    basicHeader.put(USER_AGENT, USER_AGENT_DATA_IPAD);
                    basicHeader.put(HOST, "members.bet365.com");
                } else {
                    basicHeader.put(USER_AGENT, USER_AGENT_DATA_FIREFOX);
                }
            }
        }
        return basicHeader;
    }

    private Browser initFirstTime(Browser browser, Connection connection) {

        Cookies cookies = browser.getCookies();
        if (cookies == null) {
            cookies = new Cookies();
            browser.setCookies(cookies);
        }
        // init cookies from db
        if (MapUtils.isEmpty(cookies.getCookieMap())) {
            List<Cookie> cookiesDB = cookieDAO.findAll(browser.getBrowserType());
            if (cookiesDB != null && cookiesDB.size() > 0) {
                // re-store cookie for logined session or basic session for the first time
                Cookies c = browser.getCookies();
                c.setCookies(cookiesDB);
                browser.setCookies(c);
                browser.getHeaders().put(COOKIE, browser.getCookies().getCookie());
            } else {
                if (connection != null)
                    browser.getCookies().putNewCookies(connection.response().cookies());
            }
        }
        return browser;
    }

    public Document redirectNavigator(String url, Browser browser) throws Exception {

        Document doc = browser.getCurrentPage();
        try {
            Connection connection = browser.getConnection();
            Cookies cookies = browser.getCookies();
            connection = navigator(url, browser).timeout(30000);
            doc = connection.get();
            initFirstTime(browser, connection);
            while (responseCode(connection) == HttpStatus.FOUND.value()) {
                String redirectLocation = connection.response().header(LOCATION);
                connection = navigator(redirectLocation, browser).timeout(30000);
                doc = connection.get();
                if (cookies == null) {
                    cookies = new Cookies();
                    browser.setCookies(cookies);
                }
                browser.getCookies().getCookieMap().putAll(connection.response().cookies());
                browser.getCookies().getCookie();
                cookieService.saveCookies(browser.getCookies(), browser.getBrowserType());
            }
        } catch (Exception e) {
            logger.error("redirectNavigator error : " + url);
            throw e;
        }

        browser.setCurrentPage(doc);
        return doc;
    }

    public Document postForm(String url, Map<String, String> formData, Browser browser) {

        Document doc = null;
        try {
            Connection connection = browser.getConnection();
            Map<String, String> headers = browser.getHeaders();
            connection = navigator(url, browser).timeout(60000).data(formData);
            doc = connection.post();
            browser.getCookies().getCookieMap().putAll(connection.response().cookies());
            browser.getCookies().getCookie();
            cookieService.saveCookies(browser.getCookies(), browser.getBrowserType());
            // browser.setCookies(cookies);
            while (responseCode(connection) == HttpStatus.FOUND.value()) {
                headers.remove(CONTENT_TYPE);
                String redirectLocation = connection.response().header(LOCATION);
                connection = navigator(redirectLocation, browser);
                doc = connection.get();
                // update current cookie
                browser.getCookies().getCookieMap().putAll(connection.response().cookies());
                browser.getCookies().getCookie();
                cookieService.saveCookies(browser.getCookies(), browser.getBrowserType());
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
        return doc;
    }

    public int responseCode(Connection connection) {

        return connection.response().statusCode();
    }

}
